package com.xiaobaibai.schedulingTask;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.xiaobaibai.common.BargainCommon;
import com.xiaobaibai.common.OrderCommon;
import com.xiaobaibai.common.UserCommon;
import com.xiaobaibai.common.WeixinCommon;
import com.xiaobaibai.entity.Coupon;
import com.xiaobaibai.entity.CouponBelong;
import com.xiaobaibai.service.ICouponBelongService;
import com.xiaobaibai.service.ICouponService;
import com.xiaobaibai.units.Last7DaysUtil;
import com.xiaobaibai.units.OrderWXNewsUnit;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.*;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class SchedulingTask {

    @Autowired
    private ICouponService couponService;

    @Autowired
    private ICouponBelongService couponBelongService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    //秒 分 时 日 月 星期 (年)
    @Scheduled(cron = "0 1 0 * * ?")//每天的凌晨00:01:00
    //砍价次数+优惠券
    private void configureTasks() {

        log.info("开始增加今日的订单数量和销售金额(带过期时间)");
        String nowDay = Last7DaysUtil.getNowDay();
        stringRedisTemplate.opsForValue().set(OrderCommon.orderCount+nowDay,String.valueOf(0),8, TimeUnit.DAYS);
        stringRedisTemplate.opsForValue().set(OrderCommon.orderAmount+nowDay,String.valueOf(0),8, TimeUnit.DAYS);

        log.info("开始清理当日的砍价词次数map");
        stringRedisTemplate.delete(BargainCommon.HelpMap);

        log.info("开始清理过期的优惠券");
        QueryWrapper<Coupon> queryWrapper=new QueryWrapper<>();
        //寻找所有有效的优惠券
        queryWrapper.select("id","coupon_invalidation_time");
        queryWrapper.eq("coupon_status",true);
        List<Coupon> list = couponService.list(queryWrapper);
        Date date=new Date();
        List<Coupon> couponFailList=new ArrayList<>();
        list.forEach(c->{
            //过期时间在当前时间之前
            if(c.getCouponInvalidationTime().before(date)){
                c.setCouponStatus(false);//设置为失效
                couponFailList.add(c);
            }
        });

        //去改变主优惠券表
        couponService.updateBatchById(couponFailList);
        //去改变领取优惠券表
        for (int i = 0; i < couponFailList.size(); i++) {
            UpdateWrapper<CouponBelong> updateWrapper=new UpdateWrapper<>();
            updateWrapper.set("status",1);
            updateWrapper.eq("coupon_id",couponFailList.get(i).getId());
            updateWrapper.eq("status",0);//只改变未使用的
            couponBelongService.update(updateWrapper);
        }
    }

    //秒 分 时 日 月 星期
    @Scheduled(cron = "3 0 0 1 * ? ")//每个月的一号,0点0分3秒进行签到缓存删除
    //每个月的第一天清空用户的签到记录表
    private void clearUserCheckin() {

        log.info("删除用户签到记录");
        Set<String> keys = stringRedisTemplate.execute((RedisCallback<Set<String>>) connection -> {
            Set<String> keysTmp = new HashSet<>();
            //在redis内部直接迭代,然后所有迭代完毕后返回结果,count设置每次迭代时的个数,如果count越小,那么会越耗时
            Cursor<byte[]> cursor = connection.scan(ScanOptions.scanOptions().match(UserCommon.monthCheckin+"*").count(10000).build());
            while (cursor.hasNext()) {
                keysTmp.add(new String(cursor.next()));
            }
            try {
                cursor.close();//网上说游标要关闭
            } catch (IOException e) {
                e.printStackTrace();
            }
            return keysTmp;
        });

        log.info("本月签到人数:{}",JSON.toJSONString(keys));

        stringRedisTemplate.execute(new SessionCallback<Object>() {
            @Override
            public Object execute(RedisOperations redisOperations) throws DataAccessException {
                redisOperations.delete(keys);
                return null;
            }
        });

        log.info("清除签到记录完成");

    }

    @Scheduled(cron = "0 55 * * * ? ")
    //每个小时的55分去redis中获取wxAccessToken存入本地
    private void getWxAccessToken(){
        OrderWXNewsUnit.token= stringRedisTemplate.opsForValue().get(WeixinCommon.WxAccessToken);
    }


}
